package com.module.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Nio工具
 * 
 * @author chenluqiang
 * @date 2019年3月21日 下午2:56:42
 *
 */
public class NIOUtils {

	private static final Logger log = LoggerFactory.getLogger(NIOUtils.class);

	public static void NioServer() throws Exception {
		// 打开socket 通道
		ServerSocketChannel serverChannel = ServerSocketChannel.open();
		// 设置非阻塞
		serverChannel.configureBlocking(false);
		serverChannel.bind(new InetSocketAddress("127.0.0.1", 2333));
		// 获取通道管理器
		Selector selector = Selector.open();
		// 将通道管理器与通道绑定，并为通道注册打开接收信息SelectionKey.OP_ACCEPT 事件;
		serverChannel.register(selector, SelectionKey.OP_ACCEPT);

		while (true) {
			// 当有注册的事件到达时，方法返回，否则阻塞。
			selector.select();
			for (SelectionKey selectionKey : selector.selectedKeys()) {
				// 如果有信息
				if (selectionKey.isAcceptable()) {
					// 跟客户端链接
					ServerSocketChannel socketChannel = (ServerSocketChannel) selectionKey.channel();
					// 设置非阻塞
					socketChannel.configureBlocking(false);
					SocketChannel channel = socketChannel.accept();
					if(channel!=null) {
						channel.configureBlocking(false);
						channel.write(ByteBuffer.wrap(new String("hello client").getBytes()));
						channel.register(selector, SelectionKey.OP_READ);
					}
				} else if (selectionKey.isReadable()) { // 如果selector有读取数据事件.
					SocketChannel clientChannel = (SocketChannel) selectionKey.channel();
					// 字节buff初始化
					ByteBuffer buffer2 = ByteBuffer.allocate(1000);
					// 通道读取
					clientChannel.read(buffer2);
					byte[] data = buffer2.array();
					String message = new String(data);
					log.info("received client:"+message);
//					return message;
					clientChannel.register(selector, SelectionKey.OP_WRITE);
				} else if(selectionKey.isWritable()) {
					serverChannel.close();
				}
			}
		}
	}

	public static String NioClient() throws Exception {
		// 打开通道
		SocketChannel clientChannel = SocketChannel.open();
		// 设置不阻塞
		clientChannel.configureBlocking(false);
		// 链接服务器
		clientChannel.connect(new InetSocketAddress("127.0.0.1", 2333));
		// 打开通道器
		Selector selector = Selector.open();
		// 将通道器与通道绑定,并注册 链接事件
		clientChannel.register(selector, SelectionKey.OP_CONNECT);

		while (true) {
			// 选择注册过的io操作的事件(第一次为SelectionKey.OP_CONNECT)
			selector.select();
			for (SelectionKey selectionKey : selector.selectedKeys()) {
				SocketChannel channel = (SocketChannel) selectionKey.channel();
				if (selectionKey.isConnectable()) { // 是否有链接
					// 设置非阻塞
					channel.configureBlocking(false);
					// 判断是否链接成功
					if (channel.isConnectionPending()) {
						channel.finishConnect(); // 如果正在连接，则完成连接
					}
					 //回写数据
		            channel.write(ByteBuffer.wrap(new String("O++++++++++++++++K!").getBytes()));
					// 注册读取事件,是否有消息传递
					channel.register(selector, SelectionKey.OP_READ);
				} else if (selectionKey.isReadable()) { // 有可读数据事件
					ByteBuffer buffer = ByteBuffer.allocate(1000);
		            channel.read(buffer);
					byte[] data = buffer.array();
					String message = new String(data);
					System.out.println("server:"+message);
					 channel.write(ByteBuffer.wrap(new String("RRRRRRRRRRRRR!").getBytes()));
//					return message;
				}
			}
		}
	}
	
	public static void main(String[] args) {
		try {
			System.out.println("启动服务器");
			NioServer();
			System.out.println("服务器启动成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
